lst-if-salary-tax 与 lst-break-continue,形成分支跟踪和循环终止记录。控制流(Control Flow) 决定了代码的执行顺序和逻辑分支。
根据 Bohm-Jacopini 定理,程序有三种基本控制结构:
| 结构 | 描述 | 关键字 |
|---|---|---|
| 顺序结构 | 语句按顺序依次执行 | (默认) |
| 选择结构 | 根据条件选择执行路径 | if-elif-else |
| 循环结构 | 重复执行某段代码 | for / while |
RULE_A/ALERT/REVIEW布尔(Boolean)代数是条件判断的数学基础:
| 运算 | 语法 | 含义 |
|---|---|---|
| 与(AND) | A and B |
两者都真才真 |
| 或(OR) | A or B |
至少一个真就真 |
| 非(NOT) | not A |
真变假,假变真 |
短路求值(Short-circuit Evaluation):
A and B:如果 A 为假,不计算 BA or B:如果 A 为真,不计算 B累进税率是现代税收制度的核心,体现’量能课税’原则:
核心公式:
\[ \large \begin{aligned} \text{应纳税额} &= \text{应纳税所得额} \times \text{税率} \\ &\quad - \text{速算扣除数} \end{aligned} \]
def calculate_tax(salary):
"""
计算个人所得税(简化版)
中国个人所得税采用7级超额累进税率
"""
# 使用if-elif-else匹配累进税率表
if salary <= 3000:
rate, deduction = 0, 0
elif salary <= 12000:
rate, deduction = 0.03, 0
elif salary <= 25000:
rate, deduction = 0.10, 210
elif salary <= 35000:
rate, deduction = 0.20, 1410
elif salary <= 55000:
rate, deduction = 0.25, 2660
elif salary <= 80000:
rate, deduction = 0.30, 4410
else:
rate, deduction = 0.35, 7160
# 应纳税所得额 = 税前工资 - 起征点(5000元)
taxable_income = salary - 5000
# 应纳税额 = 应纳税所得额 × 税率 - 速算扣除数
tax = max(0, taxable_income * rate - deduction)
after_tax = salary - tax
return tax, after_tax# 测试不同收入水平
salaries = [2500, 5000, 15000, 30000, 60000, 100000]
print('工资扣税计算:')
print('-' * 60)
for salary in salaries:
tax, after_tax = calculate_tax(salary)
tax_rate = tax / salary * 100 if salary > 0 else 0
print(f'税前工资: {salary:8.2f}元 | 税额: {tax:7.2f}元 | 税率: {tax_rate:5.2f}% | 税后: {after_tax:8.2f}元')工资扣税计算:
------------------------------------------------------------
税前工资: 2500.00元 | 税额: 0.00元 | 税率: 0.00% | 税后: 2500.00元
税前工资: 5000.00元 | 税额: 0.00元 | 税率: 0.00% | 税后: 5000.00元
税前工资: 15000.00元 | 税额: 790.00元 | 税率: 5.27% | 税后: 14210.00元
税前工资: 30000.00元 | 税额: 3590.00元 | 税率: 11.97% | 税后: 26410.00元
税前工资: 60000.00元 | 税额: 12090.00元 | 税率: 20.15% | 税后: 47910.00元
税前工资: 100000.00元 | 税额: 26090.00元 | 税率: 26.09% | 税后: 73910.00元
elif 是 ‘else if’ 的缩写当需要同时满足多个条件时:
| 写法 | 代码 | 适用场景 |
|---|---|---|
| 嵌套 if | if A: → if B: |
条件有层级关系 |
| 逻辑运算 | if A and B: |
条件独立并列 |
选择建议:代码可读性优先
课堂规则逻辑(多条件嵌套判断):
def generate_signal(price, ma20, ma60, volume, avg_volume, rsi):
"""基于课堂数值字段的多条件嵌套判断"""
signal = 'REVIEW'
reason = []
# 第一层:判断市场趋势(均线排列)
if ma20 > ma60:
reason.append('均线多头')
# 第二层:价格是否突破均线
if price > ma20:
reason.append('突破20日均线')
# 第三层:量价配合 + RSI确认
if volume > avg_volume * 1.2 and rsi < 70:
signal = 'RULE_A'
reason.append('放量上涨')
elif ma20 < ma60:
reason.append('均线空头')
if price < ma20:
reason.append('跌破20日均线')
if volume > avg_volume * 1.2 and rsi > 30:
signal = 'RULE_B'
reason.append('放量下跌')
else:
reason.append('均线接近,进入核对')
return signal, '; '.join(reason)# 测试不同市场情景
signals = [
(18.5, 18.0, 17.5, 2500000, 2000000, 45),
(18.5, 18.0, 17.5, 1500000, 2000000, 65),
(18.5, 18.0, 17.5, 2500000, 2000000, 75),
(16.5, 18.0, 17.5, 2500000, 2000000, 25),
]
print('课堂规则状态分析:')
print('-' * 80)
for price, ma20, ma60, volume, avg_vol, rsi in signals:
signal, reason = generate_signal(price, ma20, ma60, volume, avg_vol, rsi)
print(f'价格={price:.1f}, MA20={ma20:.1f}, MA60={ma60:.1f}, 状态={signal}, 原因=[{reason}]')课堂规则状态分析:
--------------------------------------------------------------------------------
价格=18.5, MA20=18.0, MA60=17.5, 状态=RULE_A, 原因=[均线多头; 突破20日均线; 放量上涨]
价格=18.5, MA20=18.0, MA60=17.5, 状态=REVIEW, 原因=[均线多头; 突破20日均线]
价格=18.5, MA20=18.0, MA60=17.5, 状态=REVIEW, 原因=[均线多头; 突破20日均线]
价格=16.5, MA20=18.0, MA60=17.5, 状态=REVIEW, 原因=[均线多头]
结果说明:上述程序结果只用于课堂判断。实际应用还需要检查时间、复权和缺失值,并比较样本外表现、交易成本和不确定性,不能直接把程序输出当作投资指令。
for 循环用于遍历序列中的每个元素:
range() 函数生成整数序列:
| 用法 | 说明 | 示例 |
|---|---|---|
range(stop) |
0 到 stop-1 | range(5) → 0,1,2,3,4 |
range(start, stop) |
start 到 stop-1 | range(1,5) → 1,2,3,4 |
range(start, stop, step) |
自定义步长 | range(0,10,2) → 0,2,4,6,8 |
复利是金融学的核心概念:利息产生利息。
\[ \large FV = PV \times (1 + r)^n \]
观察重点:循环逐年将利息计入余额,再与单利基准比较。
import numpy as np
# ===== 案例1:复利终值计算 =====
principal = 10000 # 本金
rate = 0.05 # 年利率5%
years = 10 # 投资10年
print('复利增长过程(打印第1年与偶数年以控制输出高度):') # 输出演示标题并说明抽样口径
print(f'{"年份":<6}{"利息":<12}{"年末余额":<12}') # 输出表头,列宽用格式符对齐
amount = principal
# range(1, years+1) 生成 [1,2,...,10],循环把每年利息计入余额
for year in range(1, years + 1):
interest = amount * rate # 当年利息
amount += interest # 累加到余额
if year == 1 or year % 2 == 0: # 仅输出首年与偶数年,保证结论行不被折叠隐藏
print(f'{year:<6}{interest:<12.2f}{amount:<12.2f}') # 输出当年利息与年末余额
# 复利 vs 单利对比
print(f'\n复利终值: {amount:.2f}元')
simple_interest = principal * (1 + rate * years)
print(f'单利对比: {simple_interest:.2f}元')
print(f'复利优势: {amount - simple_interest:.2f}元')复利增长过程(打印第1年与偶数年以控制输出高度):
年份 利息 年末余额
1 500.00 10500.00
2 525.00 11025.00
4 578.81 12155.06
6 638.14 13400.96
8 703.55 14774.55
10 775.66 16288.95
复利终值: 16288.95元
单利对比: 15000.00元
复利优势: 1288.95元
统一口径:以下固定序列仅用于课堂计算演示,不是市场样本;手算与 NumPy 均使用样本标准差(ddof=1)。
import numpy as np # 导入数值运算工具以核对手算结果
daily_returns = [0.02, -0.01, 0.03, -0.02, 0.01, 0.04, -0.03, 0.02, -0.01, 0.01] # 设置非市场观测的固定课堂演示序列
sample_size = len(daily_returns) # 记录样本观测数以使用 n-1 分母
mean_daily_return = sum(daily_returns) / sample_size # 计算日收益率样本均值
squared_deviation_sum = sum((daily_return - mean_daily_return) ** 2 for daily_return in daily_returns) # 累计离差平方和
sample_variance = squared_deviation_sum / (sample_size - 1) # 按 ddof=1 口径计算样本方差
annualization_factor = np.sqrt(252) # 按252个交易日构造年化因子
manual_annualized_volatility = np.sqrt(sample_variance) * annualization_factor # 将手算样本标准差年化
numpy_annualized_volatility = np.std(daily_returns, ddof=1) * annualization_factor # 用相同样本口径调用 NumPy 核对
calculation_difference = abs(manual_annualized_volatility - numpy_annualized_volatility) # 计算两种路径的绝对差异
print(f'样本口径: n={sample_size}, ddof=1, 年化因子=252') # 显示可核对的统计口径
print(f'手算={manual_annualized_volatility:.2%} | NumPy={numpy_annualized_volatility:.2%} | 差异={calculation_difference:.2e}') # 紧凑呈现一致的年化结果样本口径: n=10, ddof=1, 年化因子=252
手算=36.04% | NumPy=36.04% | 差异=0.00e+00
核心优势:
while 循环在条件为真时重复执行:
金融应用:迭代求解(牛顿法、梯度下降)
\[ \large x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)} \]
import numpy as np
def sqrt_newton(x, tolerance=1e-6, max_iter=100):
"""
牛顿迭代法计算√2
迭代公式: x_{n+1} = 0.5 * (x_n + S/x_n)
"""
S = 2.0
x_old = x
print(f'牛顿法求√{S}:')
print(f'{"迭代":<6}{"近似值":<15}{"误差":<15}')
print('-' * 40)
for i in range(max_iter):
x_new = 0.5 * (x_old + S / x_old) # 牛顿迭代
error = abs(x_new - x_old) # 绝对误差
print(f'{i+1:<6}{x_new:<15.10f}{error:<15.10f}')
if error < tolerance: # 检查收敛
print(f'\n收敛! 迭代{i+1}次后达到精度要求')
break
x_old = x_new
else:
print(f'\n警告: 未在{max_iter}次内收敛')
return x_new牛顿法求√2.0:
迭代 近似值 误差
----------------------------------------
1 1.5000000000 0.5000000000
2 1.4166666667 0.0833333333
3 1.4142156863 0.0024509804
4 1.4142135624 0.0000021239
5 1.4142135624 0.0000000000
收敛! 迭代5次后达到精度要求
近似值: 1.4142135624
实际值: 1.4142135624
误差: 2.22e-16
核心要点:
金融应用:隐含波动率
课堂输入(非市场观测):\(S=100\)、\(K=105\)、\(T=1\)、\(r=5\%\)、期权价格 \(8.02\);在 \(0.01\%\) 至 \(300\%\) 内检查根并求解。
import numpy as np # 提供 Black-Scholes 公式所需的对数和平方根运算
from scipy.optimize import brentq # 调用保持在给定区间内的 Brent 有界求根器
from scipy.stats import norm # 计算标准正态分布累积概率
def black_scholes_call_price(spot_price, strike_price, time_years, risk_free_rate, volatility): # 计算不分红欧式看涨期权理论价格
d1 = (np.log(spot_price / strike_price) + (risk_free_rate + 0.5 * volatility**2) * time_years) / (volatility * np.sqrt(time_years)) # 标准化到期价格阈值
d2 = d1 - volatility * np.sqrt(time_years) # 将 d1 调整为行权概率阈值
return spot_price * norm.cdf(d1) - strike_price * np.exp(-risk_free_rate * time_years) * norm.cdf(d2) # 返回 Black-Scholes 看涨期权价格
def solve_implied_volatility(option_price, spot_price=100, strike_price=105, time_years=1, risk_free_rate=0.05, lower_bound=0.0001, upper_bound=3): # 在给定波动率边界内反解隐含波动率
lower_error = black_scholes_call_price(spot_price, strike_price, time_years, risk_free_rate, lower_bound) - option_price # 计算下界价格误差
upper_error = black_scholes_call_price(spot_price, strike_price, time_years, risk_free_rate, upper_bound) - option_price # 计算上界价格误差
if lower_error * upper_error > 0: # 检查两端误差是否异号以确认区间内存在根
return None, '失败:期权价格超出求解边界' # 明确返回失败状态而不产生无效波动率
pricing_error = lambda volatility: black_scholes_call_price(spot_price, strike_price, time_years, risk_free_rate, volatility) - option_price # 定义理论价与输入价的差额函数
bounded_volatility = brentq(pricing_error, lower_bound, upper_bound, xtol=1e-8) # 在有效区间内定位价格误差的根
return bounded_volatility, '求解成功' # 返回有界解与明确状态
teaching_option_price = 8.02 # 设置非市场观测的确定性课堂价格输入
estimated_volatility, solver_status = solve_implied_volatility(teaching_option_price) # 调用有界求根器并接收状态
print('课堂输入(非市场观测): S=100, K=105, T=1, r=5%, 价格=8.02') # 披露参数性质与完整输入
if estimated_volatility is None: # 根据边界检查结果分流成功与失败状态
print(solver_status) # 在无根时显示明确失败原因
else: # 在找到区间根时执行价格核对
reconstructed_price = black_scholes_call_price(100, 105, 1, 0.05, estimated_volatility) # 用反解波动率重新计算理论价
print(f'{solver_status}: IV={estimated_volatility:.2%} | 核对价={reconstructed_price:.4f} | 残差={abs(reconstructed_price - teaching_option_price):.2e}') # 紧凑呈现解、核对价与定价残差课堂输入(非市场观测): S=100, K=105, T=1, r=5%, 价格=8.02
求解成功: IV=20.00% | 核对价=8.0200 | 残差=1.69e-11
| 语句 | 作用 | 类比 |
|---|---|---|
break |
立即退出整个循环 | 紧急刹车 |
continue |
跳过本次迭代,继续下一次 | 跳过一站 |
观察重点:break 在首个正收益处结束;continue 跳过负收益后继续统计。
# ===== break演示 =====
print('break演示(找到第一个正收益):')
returns = [-0.02, 0.03, -0.01, 0.04, 0.01, -0.03, 0.02]
for i, ret in enumerate(returns):
if ret > 0:
print(f' 第{i+1}天: {ret:.2%}')
break # 找到后立即退出
# ===== continue演示 =====
print('\ncontinue演示(跳过负收益):')
positive_count = 0
for ret in returns:
if ret < 0:
continue # 负收益直接跳过
positive_count += 1
print(f' 正收益: {ret:.2%}')
print(f'\n正收益天数: {positive_count}天')break演示(找到第一个正收益):
第2天: 3.00%
continue演示(跳过负收益):
正收益: 3.00%
正收益: 4.00%
正收益: 1.00%
正收益: 2.00%
正收益天数: 4天
观察重点:内层循环识别对角线,每轮正常结束后执行 else。
嵌套循环演示(2×2矩阵):
(0, 0): 对角线元素
第0行完成
(1, 1): 对角线元素
第1行完成
for-else 规则:
else 块在循环正常完成时执行break 中断,else 块不会执行*args*args 收集所有位置参数为元组,使函数能接受任意数量的参数:
折现公式:
\[ \large PV = \sum_{t=1}^{n} \frac{CF_t}{(1+r)^t} \]
观察重点:*args 接收任意期数的现金流,循环逐期折现并累加。
def PV(R, *NCF, verbose=False):
"""
计算各期现金流现值合计
PV = Σ(CF_t / (1+r)^t),t 自 1 起
*NCF 接收任意数量的现金流
"""
pv = 0
n = 1
for cf in NCF:
discount_factor = 1 / (1 + R) ** n # 第n期折现因子
discounted_cf = cf * discount_factor # 该期现金流现值
pv += discounted_cf # 逐期累加
if verbose:
print(f' 第{n}期: 现金流={cf:8.2f}, 折现因子={discount_factor:.6f}, 现值={discounted_cf:8.2f}')
n += 1
if verbose:
print(f'现值总和: {pv:.2f}元') # 输出折现合计供课堂核对
return pv# 案例1:简单投资项目(区分两种口径)
pv1 = PV(0.05, -10000, 8000, 12000) # 期初流出也被当作第1期现金流折现
npv_t0 = -10000 + 8000 / 1.05 + 12000 / 1.05 ** 2 # 标准口径:期初流出在t=0不折现、流入自t=1起
print(f'案例1: 全部自第1期折现的合计 {pv1:.2f}元;期初流出口径NPV {npv_t0:.2f}元\n') # 两种口径并列展示
# 案例2:多期项目(verbose展示逐期折现过程)
project_flows = [-50000, 15000, 20000, 25000] # 四期课堂示例现金流
pv2 = PV(0.08, *project_flows, verbose=True)
# 案例3:债券定价(仅输出合计)
bond_flows = [50] * 9 + [1050] # 10年期,票面5%,面值1000
pv_bond = PV(0.06, *bond_flows)
print(f'\n案例3: 债券现值 {pv_bond:.2f}元') # 输出债券定价结果案例1: 全部自第1期折现的合计 8098.48元;期初流出口径NPV 8503.40元
第1期: 现金流=-50000.00, 折现因子=0.925926, 现值=-46296.30
第2期: 现金流=15000.00, 折现因子=0.857339, 现值=12860.08
第3期: 现金流=20000.00, 折现因子=0.793832, 现值=15876.64
第4期: 现金流=25000.00, 折现因子=0.735030, 现值=18375.75
现值总和: 816.18元
案例3: 债券现值 926.40元
递归三要素:
数学归纳法的程序化实现:
\[ \large n! = n \times (n-1)! \]
\[ \large F(n) = F(n-1) + F(n-2) \]
观察重点:先命中基准情形,再沿调用链逐层回传结果。
import numpy as np
# ===== 阶乘 =====
def factorial(n):
"""n! = n × (n-1)!,基准: 0!=1, 1!=1"""
if n <= 1:
return 1
return n * factorial(n - 1)
print('阶乘计算:')
for n in [1, 5, 10, 20]:
print(f'{n}! = {factorial(n)}')
# ===== 斐波那契 =====
def fibonacci(n):
"""F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)"""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(f'\n斐波那契数列前10项:')
print([fibonacci(i) for i in range(10)])阶乘计算:
1! = 1
5! = 120
10! = 3628800
20! = 2432902008176640000
斐波那契数列前10项:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
观察重点:先计算终端价值,再按风险中性概率逐层回推至根节点。
import numpy as np
def binomial_tree(S, K, T, r, sigma, n, call=True):
"""
Cox-Ross-Rubinstein二叉树模型
u = e^(σ√dt), d = 1/u, p = (e^(r·dt) - d) / (u - d)
"""
dt = T / n
u = np.exp(sigma * np.sqrt(dt)) # 上涨因子
d = 1 / u # 下跌因子
p = (np.exp(r * dt) - d) / (u - d) # 风险中性概率
# 终端节点期权价值
option_values = np.zeros(n + 1)
for j in range(n + 1):
S_T = S * (u ** j) * (d ** (n - j))
if call:
option_values[j] = max(S_T - K, 0)
else:
option_values[j] = max(K - S_T, 0)
# 从终端向根回推
for i in range(n - 1, -1, -1):
for j in range(i + 1):
option_values[j] = np.exp(-r * dt) * (
p * option_values[j + 1] + (1 - p) * option_values[j]
)
return option_values[0]
# 注:生产环境中可使用n=100或更高步数以提升精度
option_price = binomial_tree(S=100, K=105, T=1, r=0.05, sigma=0.2, n=20)
print(f'二叉树模型期权价格: {option_price:.2f}元')二叉树模型期权价格: 8.11元
| 方法 | 时间复杂度 | 说明 |
|---|---|---|
| 朴素递归 | \(O(2^n)\) | 指数级,大量重复计算 |
| 动态规划 | \(O(n^2)\) / \(O(n)\) | 避免重复,从底向上 |
最佳实践:金融应用中必须优化递归
Python 变量查找遵循 LEGB 层次:
| 层级 | 名称 | 范围 |
|---|---|---|
| L (Local) | 局部作用域 | 函数内 |
| E (Enclosing) | 闭包作用域 | 嵌套函数的外层 |
| G (Global) | 模块作用域 | 文件内 |
| B (Built-in) | 内置作用域 | Python 内置 |
x = 10 # 全局变量
y = 20
def func_local():
"""局部变量遮蔽全局变量"""
x = 5 # 局部变量,不影响全局x
print(f'函数内x: {x} (局部)')
def func_global():
"""使用global修改全局变量"""
global y
y = 50
print(f'函数内y: {y} (修改后的全局)')
def func_enclosing():
"""闭包:内层函数访问外层变量"""
z = 100
def inner():
return x + z # x来自Global, z来自Enclosing
return inner()初始状态:
全局x: 10, 全局y: 20
函数内x: 5 (局部)
func_local()后, 全局x: 10 (未改变)
函数内y: 50 (修改后的全局)
func_global()后, 全局y: 50 (已修改)
闭包结果: 110
global(除非绝对必要),防止代码维护困难lambda 是匿名的单行函数:
| 特点 | 说明 |
|---|---|
| 匿名 | 不需要函数名 |
| 简洁 | 只能是单个表达式 |
| 函数式 | 可作为参数传递给高阶函数 |
观察重点:lambda 将单个表达式封装为函数,可直接用于收益率与组合净值计算。
# 基本lambda函数
square = lambda x: x**2
cube = lambda x: x**3
print('lambda函数演示:')
print(f'平方: {square(5)} = {square(5)}')
print(f'立方: {cube(5)} = {cube(5)}')
# 金融收益率计算
simple_return = lambda initial, final: (final - initial) / initial
compound_return = lambda initial, rate, periods: initial * (1 + rate) ** periods - initial
print(f'\n简单收益率: {simple_return(100, 110):.2%}')
print(f'复利收益: {compound_return(10000, 0.05, 10):.2f}')
# 投资组合净值
net_value = lambda prices, shares: sum(p * s for p, s in zip(prices, shares))
prices = [10.5, 22.3, 15.8]
shares = [100, 200, 150]
print(f'\n投资组合净值: {net_value(prices, shares):.2f}元')lambda函数演示:
平方: 25 = 25
立方: 125 = 125
简单收益率: 10.00%
复利收益: 6288.95
投资组合净值: 7880.00元
观察重点:map 做变换,filter 做筛选,sorted 按键函数排序。
stocks = ['贵州茅台', '五粮液', '招商银行']
prices = [1850, 220, 45]
# map:对每个元素应用函数
formatted = list(map(lambda x: f'{x}元', prices))
print(f'格式化价格: {formatted}')
# filter:过滤符合条件的元素
expensive = list(filter(lambda p: p[1] > 200, zip(stocks, prices)))
print(f'高价股票: {[s + "=" + str(p) + "元" for s, p in expensive]}')
# sorted:自定义排序
portfolio = [
{'name': '贵州茅台', 'return': 0.15},
{'name': '五粮液', 'return': 0.08},
{'name': '招商银行', 'return': 0.12}
]
sorted_portfolio = sorted(portfolio, key=lambda x: x['return'], reverse=True)
print(f'\n按收益率排序:')
for stock in sorted_portfolio:
print(f" {stock['name']}: {stock['return']:.2%}")格式化价格: ['1850元', '220元', '45元']
高价股票: ['贵州茅台=1850元', '五粮液=220元']
按收益率排序:
贵州茅台: 15.00%
招商银行: 12.00%
五粮液: 8.00%
课堂状态:
收益率= 6.00%: 信号=ABOVE_ASSUMED_THRESHOLD
收益率=-3.00%: 信号=ALERT
收益率= 2.00%: 信号=REVIEW
收益率=-1.00%: 信号=REVIEW
收益率= 8.00%: 信号=ABOVE_ASSUMED_THRESHOLD
| 场景 | 推荐 | 原因 |
|---|---|---|
| 简单单行逻辑 | ✅ lambda | 简洁高效 |
| 高阶函数参数 | ✅ lambda | 避免定义独立函数 |
| 复杂多行逻辑 | ❌ 用 def |
可读性优先 |
| 需要文档字符串 | ❌ 用 def |
lambda 无法添加 docstring |
salary、rate 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#题目一
salary = 8000 # 基本工资
if salary <= 5000: # 判断基本工资是否小于等于5000
rate = 0 # 基本工资小于等于5000,不扣税,即扣税率为0%
else: # 不满足以上条件时
rate = 0.05 # 基本工资大于5000,扣税率为0.05,即5%
# 计算税后工资,基本工资-扣税,扣税额为超过3000部分的乘以扣税率
salary = salary - (salary - 5000) * rate
print("税后工资为:%d" % salary) # 将税后工资打印输出运行后核对:核对 salary、rate 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。
拓展练习:只改变一个关键输入或业务场景,先预测输出如何变化,再运行验证并解释变化原因。
sum_salary、salary_list、salary 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。# 注:该代码块包含input()交互输入,渲染时无法执行
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#题目二
sum_salary = 0
salary_list = [] # 定义列表salary_list
salary = 0 # 初始化薪资变量为0
while True: # 条件循环
salary = input('请输入员工的薪资,输入Q结束计算:') # 获取用户键盘输入
if salary.upper() == 'Q': # 条件判断:salary.upper() == 'Q'
print('程序结束') # 输出程序结束
break # 跳出循环
elif int(salary) <= 0: # 否则判断:int(salary) <= 0
print('您输入的数值有误,请重新输入') # 输出您输入的数值有误,请重新输入
continue # 跳过本次迭代
salary_list.append(salary) # 将有效薪资数据添加到列表
sum_salary += int(salary) # 更新sum_salary的值
print(len(salary_list)) # 输出数据长度
print(sum_salary) # 输出薪资数据运行后核对:核对 sum_salary、salary_list、salary 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。
拓展练习:把输入表替换为本地中国上市公司数据的同结构子集;指出必须保持的字段、数据类型和质量检查。
Ri、Ai、TR、TRij 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。# 注:该代码块包含缩进错误的填空代码,需要在平台上完成
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#题目三
Ri=[0.15,0.20,-0.10,0.35] #收益率序列
Ai=[0.3,0.2,0.3,0.2] #权重序列
TR=0 # 初始化投资组合期望报酬率为0
for j in range(len(Ri)): # 遍历range(len(Ri))中的每个j
TRij=Ri[j]*Ai[j] # 计算第j项资产的加权收益贡献(收益率×权重)
TR+=TRij # 更新TR的值
print("投资组合的期望报酬率为:{:.2f}".format(TR)) # 输出投资组合的期望报酬率为:{:.2f}TRij 比循环体多缩进,而 TR += TRij 又少缩进;标准 Python 会报 IndentationError,不会产生投资组合结果。import numpy as np # 导入数值工具执行有限值与权重检查
def portfolio_expected_return(return_rates, weights): # 定义可核对的组合收益接口
returns = np.asarray(return_rates, dtype=float) # 转换收益率输入
allocation = np.asarray(weights, dtype=float) # 转换权重输入
if returns.shape != allocation.shape or returns.ndim != 1: # 检查一维长度一致
raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查') # 形状不匹配时停止
if not np.isfinite(returns).all() or not np.isfinite(allocation).all(): # 检查有限值
raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查') # 非有限值时停止
if not np.isclose(allocation.sum(), 1.0): # 检查权重和
raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查') # 权重口径不合格时停止
return float(np.dot(returns, allocation)) # 返回组合期望收益率运行后核对:核对 Ri、Ai、TR、TRij 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。
拓展练习:只改变一个关键输入或业务场景,先预测输出如何变化,再运行验证并解释变化原因。
lst-if-salary-tax 与 lst-break-continue,形成分支跟踪和循环终止记录。float;课堂阈值 −3%/3%,只用于语法演示。changes=[-.04,-.03,0,.03,.05]; labels=[] # 生成changes以承接当前分析步骤
for change in changes: # 计算相邻年度指标的百分点变化
if change < -.03: labels.append('下跌核对') # 计算相邻年度指标的百分点变化
elif change > .03: labels.append('上涨核对') # 计算相邻年度指标的百分点变化
else: labels.append('区间内') # 把本轮计算结果追加到有序检查列表
i=0; trace=[] # 生成i以承接当前分析步骤
while i<len(changes): # 在显式终止条件下逐轮更新状态轨迹
trace.append((i,changes[i])); i+=1 # 把本轮计算结果追加到有序检查列表
assert labels==['下跌核对','区间内','区间内','区间内','上涨核对'] # 检查labels满足预声明的等式或边界
print(labels,trace) # 输出labels、trace供核对结果continue 跳过而 break 终止。< 与 <=;把课堂阈值写成交易规则。[商业大数据分析与应用]